package com.louis.springboot.demo.config;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Map;
import java.util.Objects;

/**
 * 操作日志切面
 *
 * @author houxiurong
 * @date 2020/9/1
 */
@Component
@Aspect
public class ActionAspect {
    private final Logger logger = LoggerFactory.getLogger(ActionAspect.class);

    @Pointcut(value = "execution(* com.louis.springboot.demo..*.*Action..*(..)) " +
            " || execution(* com.louis.springboot.demo..*.*Controller..*(..)) ")
    public void aspect() {
    }

    @Before("aspect()")
    public void before(JoinPoint joinPoint) {
        logger.info("the request details:");
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // log 请求内容
        logger.info("请求url: {}", request.getRequestURL().toString());
        logger.info("请求方法: {}", request.getMethod());
        String className = joinPoint.getSignature().getDeclaringTypeName();
        logger.info("执行的类名: {}", "(" + className.substring(className.lastIndexOf(".") + 1) + ".java)");
        logger.info("执行的方法名: {}", joinPoint.getSignature().getName());
        logger.info("参数: {}", Arrays.toString(joinPoint.getArgs()));
        //log 方法参数
        Enumeration<String> enu = request.getParameterNames();
        while (enu.hasMoreElements()) {
            String paraName = enu.nextElement();
            logger.info(paraName + ":    {}", request.getParameter(paraName));
        }
    }

    @Around("aspect()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args=joinPoint.getArgs();
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String className = joinPoint.getSignature().getDeclaringTypeName();
        String methodName = joinPoint.getSignature().getName();
        String method = request.getMethod().toLowerCase();
        try {
            // 对于业务抛出异常的记录就处理
            long start = System.currentTimeMillis();
            Object rvt = joinPoint.proceed(args);
            long end = System.currentTimeMillis();
            logger.info("-----------------------------------");
            logger.info("请求[{}]的执行时间为[{}]ms,请求param为[{}]", request.getRequestURL(), (start - end), getRequestParamStr(request.getParameterMap()));
            logger.info("-----------------------------------");

            if (method.equals("options")) {
                return rvt;
            }
            // 记录请求日志
            return rvt;
        } catch (Exception e) {
            throw e;
        }
    }

    /**
     * 配置最后通知
     */
    @After(value = "aspect()")
    public void after(){

    }

    private String getRequestParamStr(Map<String, String[]> parameterMap) {
        if (parameterMap == null || parameterMap.size() == 0) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
            sb.append(entry.getKey()).append(":").append(StringUtils.join(entry.getValue(), ",")).append(" ");
        }
        return sb.toString();
    }

}
